home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MACD 5
/
MACD 5.bin
/
workbench
/
commodity
/
cgxdpms.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-05-09
|
12KB
|
651 lines
#define __USE_SYSBASE 1
#include <clib/alib_protos.h>
#include <exec/alerts.h>
#include <exec/execbase.h>
#include <exec/memory.h>
#include <intuition/intuitionbase.h>
#include <libraries/cybergraphics.h>
#include <proto/commodities.h>
#include <proto/cybergraphics.h>
#include <proto/dos.h>
#include <proto/exec.h>
#include <proto/intuition.h>
#include <proto/icon.h>
#include <proto/utility.h>
#include <workbench/startup.h>
#include <string.h>
/* Compiler specific stuff. */
#define SAVEDS __saveds
#define ASM __asm
#define REG(x) register __ ## x
#define STKARGS __stdargs
#define VERSION "1.0"
#define DATE "9.5.97"
/******************** Global variables ********************/
struct NewBroker NewBroker =
{
NB_VERSION,
"CGXDPMS",
"CGXDPMS " VERSION "by Magnus Holmgren",
"DPMS manager for CyberGraphX",
NBU_UNIQUE, 0, 0,
NULL, 0
};
struct Library *CxBase;
struct Library *CyberGfxBase;
struct DosLibrary *DOSBase;
struct Library *IconBase;
struct IntuitionBase *IntuitionBase;
struct ExecBase *SysBase;
struct Library *UtilityBase;
struct MsgPort *CxPort;
struct WBStartup *WBMsg;
CxObj *Broker, *Sender, *Custom;
LONG StandbyTime, SuspendTime, OffTime, IETime;
LONG StandbyCounter, SuspendCounter, OffCounter;
LONG SendShift, NoMouse, State, FinalState;
struct InputEvent ShiftDown, ShiftUp;
#define DEF_CXPRI 1
#define DEF_STANDBY 20
#define DEF_SUSPEND 20
#define DEF_OFF 20
#define DEF_SENDSHIFT 1
#define ID_SENDER 49
#define ID_CUSTOM 17
#define MAGIC ( APTR ) 87654321L
struct Args
{
LONG *CxPriority;
LONG *StandbyTime;
LONG *SuspendTime;
LONG *OffTime;
LONG *ShiftTime;
LONG SendShift;
LONG NoMouse;
};
#define TEMPLATE "CX_PRIORITY/K/N,STANDBYTIME/K/N,SUSPENDTIME/K/N,OFFTIME/K/N,SHIFTTIME/K/N,SENDSHIFT/S,NOMOUSE/S"
/******************** Startup code ********************/
static LONG Main( VOID );
SAVEDS LONG
Startup( VOID )
{
LONG r;
SysBase = *( ( struct ExecBase ** ) 4 );
{
struct Process *thisTask = ( struct Process * ) FindTask( NULL );
if( !thisTask->pr_CLI )
{
/* Handle Workbench startup message */
struct MsgPort *port = &thisTask->pr_MsgPort;
WaitPort( port );
WBMsg = ( struct WBStartup * ) GetMsg( port );
}
}
SetSignal( 0, SIGBREAKF_CTRL_C );
if( SysBase->LibNode.lib_Version >= 37 )
{
r = Main();
}
else
{
r = 100;
}
if( WBMsg )
{
Forbid();
ReplyMsg( ( struct Message * ) WBMsg );
}
return( r );
}
/******************** String constants ********************/
static const TEXT Ver[] = "$VER: CGXDPMS " VERSION " (" DATE ")";
/******************** Misc ********************/
static LONG
MyRequest( STRPTR title, STRPTR body, STRPTR gads, ... )
{
struct EasyStruct es;
es.es_StructSize = sizeof( es );
es.es_Flags = 0;
es.es_Title = title;
es.es_TextFormat = body;
es.es_GadgetFormat = gads;
return( EasyRequestArgs( NULL, &es, NULL, &gads + 1 ) );
}
static VOID
ErrRequest( STRPTR body, ... )
{
if( WBMsg )
{
MyRequest( "CGXDPMS error message", body, "Quit", &body + 1 );
}
else
{
VPrintf( body, &body + 1 );
}
}
/******************** Libs ********************/
static struct Library *
OpenLib( STRPTR name, LONG ver )
{
struct Library *lib;
if( !( lib = OpenLibrary( name, ver ) ) )
{
ErrRequest( "Couldn't open %s\nversion %ld or higher!", name, ver );
}
return( lib );
}
#define CloseLib(lib) CloseLibrary( ( struct Library * ) lib )
static VOID
CloseLibs( VOID )
{
if( DOSBase )
{
CloseLib( DOSBase );
CloseLib( IntuitionBase );
CloseLib( UtilityBase );
CloseLib( CyberGfxBase );
CloseLib( CxBase );
}
}
static BOOL
OpenLibs( VOID )
{
BOOL rc = FALSE;
if( DOSBase = ( struct DosLibrary * ) OpenLibrary( "dos.library", 37 ) )
{
if( IntuitionBase = ( struct IntuitionBase * ) OpenLibrary( "intuition.library", 37 ) )
{
if( ( UtilityBase = OpenLib( "utility.library", 37 ) )
&& ( CyberGfxBase = OpenLib( "cybergraphics.library", 40 ) )
&& ( CxBase = OpenLib( "commodities.library", 37 ) ) )
{
rc = TRUE;
}
}
else
{
Alert( AT_Recovery | AN_Unknown | AG_OpenLib | AO_Intuition );
}
}
else
{
Alert( AT_Recovery | AN_Unknown | AG_OpenLib | AO_DOSLib );
}
return( rc );
}
/******************** Argument parsing ********************/
static LONG
GetTimeTT( const struct DiskObject *icon, STRPTR name, LONG def )
{
STRPTR str;
LONG val;
val = def;
if( str = FindToolType( icon->do_ToolTypes, name ) )
{
if( StrToLong( str, &val ) == -1 )
{
MyRequest( "CGXDMPS Warning", "Argument for %s should be numeric.\nUsing default (%ld).", name, def );
val = def;
}
}
return( SMult32( val, 60 ) );
}
static BOOL
ParseWBArgs( VOID )
{
BOOL rc = FALSE;
if( IconBase = OpenLib( "icon.library", 37 ) )
{
struct DiskObject *icon;
BPTR oldDir;
oldDir = CurrentDir( WBMsg->sm_ArgList[ 0 ].wa_Lock );
/* Lazy parsing: Ignore any multiselected icons... */
if( icon = GetDiskObject( WBMsg->sm_ArgList[ 0 ].wa_Name ) )
{
NewBroker.nb_Pri = GetTimeTT( icon, "CX_PRIORITY", DEF_CXPRI );
StandbyTime = GetTimeTT( icon, "STANDBYTIME", DEF_STANDBY );
SuspendTime = GetTimeTT( icon, "SUSPENDTIME", DEF_SUSPEND );
OffTime = GetTimeTT( icon, "OFFTIME", DEF_OFF );
IETime = GetTimeTT( icon, "SHIFTTIME", DEF_SENDSHIFT );
SendShift = ( LONG ) FindToolType( icon->do_ToolTypes, "SENDSHIFT" );
NoMouse = ( LONG ) FindToolType( icon->do_ToolTypes, "NOMOUSE" );
rc = TRUE;
FreeDiskObject( icon );
}
else
{
ErrRequest( "Couldn't get program icon!" );
}
CurrentDir( oldDir );
CloseLibrary( IconBase );
}
else
{
ErrRequest( "Couldn't open icon.library\nversion 37 or higher!" );
}
return( rc );
}
static LONG
GetTime( LONG *val, LONG def )
{
LONG rc;
rc = def;
if( val )
{
rc = *val;
}
return( SMult32( rc, 60 ) );
}
static BOOL
ParseCLIArgs( VOID )
{
struct Args args;
struct RDArgs *rdarg;
BOOL rc = FALSE;
memset( &args, 0, sizeof( args ) );
if( rdarg = ReadArgs( TEMPLATE, ( LONG * ) &args, NULL ) )
{
NewBroker.nb_Pri = GetTime( args.CxPriority, DEF_CXPRI );
StandbyTime = GetTime( args.StandbyTime, DEF_STANDBY );
SuspendTime = GetTime( args.SuspendTime, DEF_SUSPEND );
OffTime = GetTime( args.OffTime, DEF_OFF );
IETime = GetTime( args.ShiftTime, DEF_SENDSHIFT );
SendShift = args.SendShift;
NoMouse = args.NoMouse;
rc = TRUE;
FreeArgs( rdarg );
}
return( rc );
}
static BOOL
ParseArgs( VOID )
{
return( ( BOOL ) ( WBMsg ? ParseWBArgs() : ParseCLIArgs() ) );
}
/******************** Commodity support ********************/
/* This function runs on the input.device task context. Thus, we need to
* set smalldata base, make sure we don't call any nasty functions, and
* generally try to do our job quickly.
*/
static SAVEDS STKARGS VOID
CxCustomFunc( register CxMsg *msg, CxObj *obj )
{
struct InputEvent *ie;
static LONG LastSecs, LastIE;
LONG diff;
ie = ( struct InputEvent * ) CxMsgData( msg );
switch( ie->ie_Class )
{
case IECLASS_RAWMOUSE:
case IECLASS_POINTERPOS:
case IECLASS_NEWPOINTERPOS:
if( NoMouse && ( ie->ie_Code == IECODE_NOBUTTON ) )
{
/* Ignore mouse movements */
break;
}
case IECLASS_RAWKEY:
if( ie->ie_position.ie_addr == MAGIC )
{
/* Ignore rawkeys we send out */
break;
}
case IECLASS_DISKREMOVED:
case IECLASS_DISKINSERTED:
StandbyCounter = StandbyTime;
SuspendCounter = SuspendTime;
OffCounter = OffTime;
if( State != DPMS_ON )
{
State = DPMS_ON;
RouteCxMsg( msg, Sender );
}
break;
case IECLASS_TIMER:
diff = ie->ie_TimeStamp.tv_secs - LastSecs;
if( ( diff > 0 ) && ( State != FinalState ) && LastSecs )
{
if( ( State < DPMS_STANDBY ) && ( StandbyCounter > 0 ) )
{
StandbyCounter -= diff;
if( StandbyCounter <= 0 )
{
State = DPMS_STANDBY;
RouteCxMsg( msg, Sender );
}
}
else if( ( State < DPMS_SUSPEND ) && ( SuspendCounter > 0 ) )
{
SuspendCounter -= diff;
if( SuspendCounter <= 0 )
{
State = DPMS_SUSPEND;
RouteCxMsg( msg, Sender );
}
}
else if( ( State < DPMS_OFF ) && ( OffCounter > 0 ) )
{
OffCounter -= diff;
if( OffCounter <= 0 )
{
State = DPMS_OFF;
RouteCxMsg( msg, Sender );
}
}
if( SendShift && ( State > DPMS_ON ) )
{
diff = ie->ie_TimeStamp.tv_secs - LastIE;
if( diff > IETime )
{
LastIE = ie->ie_TimeStamp.tv_secs;
ShiftDown.ie_TimeStamp = ie->ie_TimeStamp;
ShiftUp.ie_TimeStamp = ie->ie_TimeStamp;
/* Hm.. Maybe this would be better to do on the
* main process' context. Oh well, not called
* often anyway. ;)
*/
AddIEvents( &ShiftDown );
}
}
}
LastSecs = ie->ie_TimeStamp.tv_secs;
break;
}
}
static VOID
FreeBroker( VOID )
{
DeleteCxObjAll( Broker );
DeleteMsgPort( CxPort );
}
static BOOL
InitBroker( VOID )
{
BOOL rc = FALSE;
ShiftUp.ie_Class = ShiftDown.ie_Class = IECLASS_RAWKEY;
ShiftDown.ie_Code = 0x60,
ShiftUp.ie_Code = IECODE_UP_PREFIX | 0x60;
ShiftUp.ie_position.ie_addr = ShiftDown.ie_position.ie_addr = MAGIC;
ShiftDown.ie_NextEvent = &ShiftUp;
StandbyCounter = StandbyTime;
SuspendCounter = SuspendTime;
OffCounter = OffTime;
State = DPMS_ON;
if( StandbyTime )
{
FinalState = DPMS_STANDBY;
}
else if( SuspendTime )
{
FinalState = DPMS_SUSPEND;
}
else
{
FinalState = DPMS_OFF;
}
if( CxPort = NewBroker.nb_Port = CreateMsgPort() )
{
LONG err;
if( Broker = CxBroker( &NewBroker, &err ) )
{
AttachCxObj( Broker, Custom = CxCustom( CxCustomFunc, ID_CUSTOM ) );
AttachCxObj( Custom, Sender = CxSender( CxPort, ID_SENDER ) );
if( CxObjError( Broker ) || CxObjError( Custom ) )
{
ErrRequest( "Not enough memory for Commodities objects!" );
}
else
{
rc = TRUE;
}
}
else if( err != CBERR_DUP )
{
ErrRequest( "Couldn't create broker!" );
}
}
else
{
ErrRequest( "Couldn't create message port!" );
}
if( !rc )
{
FreeBroker();
}
return( rc );
}
static VOID
HandleEvent( VOID )
{
struct Screen *wb;
/* Configurable screen name? Maybe for 1.1... */
if( wb = LockPubScreen( "Workbench" ) )
{
/* Passing args via globals isn't the best perhaps, but it works. ;) */
CVideoCtrlTags( &wb->ViewPort,
SETVC_DPMSLevel, State,
TAG_DONE );
UnlockPubScreen( NULL, wb );
}
}
static BOOL
HandleCxPort( VOID )
{
CxMsg *msg;
BOOL run = TRUE;
while( msg = ( CxMsg * ) GetMsg( CxPort ) )
{
LONG id, type;
id = CxMsgID( msg );
type = CxMsgType( msg );
ReplyMsg( ( struct Message * ) msg );
switch( type )
{
case CXM_IEVENT:
HandleEvent();
break;
case CXM_COMMAND:
switch( id )
{
case CXCMD_DISABLE:
ActivateCxObj( Broker, FALSE );
break;
case CXCMD_ENABLE:
ActivateCxObj( Broker, TRUE );
break;
case CXCMD_KILL:
run = FALSE;
break;
}
break;
}
}
return( run );
}
/******************** Main program ********************/
static VOID
MainLoop( VOID )
{
LONG cxMask = 1 << CxPort->mp_SigBit;
BOOL run = TRUE;
ActivateCxObj( Broker, TRUE );
while( run )
{
LONG sigs;
sigs = Wait( cxMask | SIGBREAKF_CTRL_C );
if( sigs & cxMask )
{
if( !HandleCxPort() )
{
run = FALSE;
}
}
if( sigs & SIGBREAKF_CTRL_C )
{
run = FALSE;
}
}
}
static LONG
Main( VOID )
{
LONG ret = RETURN_FAIL;
if( OpenLibs() )
{
if( ParseArgs() )
{
if( InitBroker() )
{
MainLoop();
ret = RETURN_OK;
FreeBroker();
}
}
CloseLibs();
}
return( ret );
}